﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using ARR.UI.Models;
using ARR.UI.Commands;
using ARR.Entities;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Media;
using ARR.Shared;
using System.ServiceModel;
using ARR.UI.EnvoyImporterService;
using System.Windows.Threading;
using ARR.UI.ArticlesService;
using ARR.UI.Views;
using Telerik.Windows.Controls.GridView;
using Telerik.Windows.Controls;
using System.Windows.Controls;
using ARR.UI.ExcelImporterService;
using ARR.UI.RangeReviewsService;

namespace ARR.UI.ViewModels
{
    public class ArticlesImporterViewModel : WorkspaceViewModel
    {

        private ICommand cancelCommand;
        private ICommand categoryMatchCommand;
        public IArticlesImporterModel model;
        private ICommand nextCommand;
        private ICommand retryCommand;
        private ICommand saveCommand;
        private ICommand startCommand;
        private ICommand unifyRepeatedsCommand;



        public ArticlesImporterViewModel(IArticlesImporterModel model)
        {
            base.DisplayName = Labels.ImportadorDeArticulos;
            this.model = model;

            IsUnifyEnabled = false;

            if (WorkspaceData.Instance.Country.IsArticleMasterSeparateFile)
            {
                CurrentStep = 0;
                HasPassedCurrentStep = null;
            }
            else
            {
                CurrentStep = 1;
                HasPassedCurrentStep = true;
                Step1ImagePath = "/Images/Pass-16.png";
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.HasPassedCurrentStep);
                CurrentStep = 2;
                HasPassedCurrentStep = true;
                Step2ImagePath = "/Images/Pass-16.png";
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.HasPassedCurrentStep);
            }
        }



        public ICommand CancelCommand
        {
            get
            {
                if (cancelCommand == null)
                {
                    cancelCommand = new RelayCommand(param => Cancel());
                }
                return cancelCommand;
            }
        }

        public ICommand CategoryMatchCommand
        {
            get
            {
                if (categoryMatchCommand == null)
                {
                    categoryMatchCommand = new RelayCommand(param => OpenCategoryMatch(param as ImporterResult));
                }
                return categoryMatchCommand;
            }
        }

        public ICommand NextCommand
        {
            get
            {
                if (nextCommand == null)
                {
                    nextCommand = new RelayCommand(param => NextStep(), p => (HasPassedCurrentStep.HasValue && HasPassedCurrentStep.Value && CurrentStep != 4));
                }
                return nextCommand;
            }
        }

        public ICommand RetryCommand
        {
            get
            {
                if (retryCommand == null)
                {
                    retryCommand = new RelayCommand(param => RetryCurrentStep(), p => (HasPassedCurrentStep.HasValue && !HasPassedCurrentStep.Value));
                }
                return retryCommand;
            }
        }

        public ICommand SaveCommand
        {
            get
            {
                if (saveCommand == null)
                {
                    saveCommand = new RelayCommand(param => SaveTempArticles());
                }
                return saveCommand;
            }
        }

        public ICommand StartCommand
        {
            get
            {
                if (startCommand == null)
                {
                    startCommand = new RelayCommand(param => NextStep(), p => CurrentStep == 0);

                }
                return startCommand;
            }
        }

        public ICommand UnifyRepeatedsCommand
        {
            get
            {
                if (unifyRepeatedsCommand == null)
                {
                    unifyRepeatedsCommand = new RelayCommand(param => UnifyRepeatedArticles(), p => IsUnifyEnabled)
                    {
                        ConfirmationMessage = Messages.UnificacionDeNombreRepetidos
                    };
                }
                return unifyRepeatedsCommand;
            }
        }

        public int CurrentStep { get; set; }

        public bool? HasPassedCurrentStep { get; set; }

        public bool IsBusy { get; set; }

        public bool IsUnifyEnabled { get; set; }

        public Visibility IsVisibleArticlesGV
        {
            get
            {
                if (TempArticles != null && TempArticles.Any())
                {
                    return Visibility.Visible;
                }

                return Visibility.Collapsed;
            }
        }

        public Visibility IsVisibleResultsGV
        {
            get
            {
                if (Results != null && Results.Any())
                {
                    return Visibility.Visible;
                }

                return Visibility.Collapsed;
            }
        }

        public ObservableCollection<ImporterResult> Results
        {
            get
            {
                return new ObservableCollection<ImporterResult>(model.Results.OrderBy(x => x.Description));
            }
        }

        public string Step1ImagePath { get; set; }

        public string Step2ImagePath { get; set; }

        public string Step3ImagePath { get; set; }

        public string Step4ImagePath { get; set; }

        public ObservableCollection<TempArticle> TempArticles
        {
            get
            {
                return model.TempArticles;
            }
        }



        public void TriggerPropertyChanged()
        {
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.TempArticles);
        }


        private void Cancel()
        {

        }


        private void NextStep()
        {
            switch (CurrentStep)
            {
                case 0:
                    RunStep1();
                    break;
                case 1:
                    RunStep2();
                    break;
                case 2:
                    RunStep3();
                    break;
                case 3:
                    RunStep4();
                    break;
            }


            OnPropertyChanged<ArticlesImporterViewModel>(p => p.Results);
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.TempArticles);
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsVisibleResultsGV);
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsVisibleArticlesGV);

            if (CurrentStep < 4)
                CurrentStep += 1;
        }

        private void OpenCategoryMatch(ImporterResult result)
        {
            var selecteds = model.Results.Where(x => x.IsSelected).Select(x => x.ItemText).Distinct();

            var match = new CategoryMatch() { CountryId = WorkspaceData.Instance.Country.Id };

            CategoryMatchView categoryMatchPopup = new CategoryMatchView();
            categoryMatchPopup.DataContext = new CategoryMatchViewModel(this.model, match, selecteds.ToArray());
            categoryMatchPopup.ShowDialog();

            if (match.CategoryId != 0)
            {
                RetryCurrentStep();
            }

        }

        private void RetryCurrentStep()
        {
            CurrentStep -= 1;
            NextStep();
        }

        private void RunStep1()
        {
            switch (WorkspaceData.Instance.Country.ArticlesImporter)
            {
                case Constants.ImportSettings.StandardExcelImporter:
                    {
                        IsBusy = true;

                        ExcelImporterServiceClient excelService = new ExcelImporterServiceClient();

                        try
                        {
                            excelService.ImportArticleMasterStep1Completed += new EventHandler<ExcelImporterService.ImportArticleMasterStep1CompletedEventArgs>(excelService_ImportArticleMasterStep1Completed);                            
                            excelService.ImportArticleMasterStep1Async(WorkspaceData.Instance.RangeReview);
                        }
                        catch (Exception ex)
                        {
                            excelService.Abort();
                            IsBusy = false;
                            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);

                            throw ex;
                        }

                        break;
                    }
                case Constants.ImportSettings.EnvoyImporter:
                    {
                        IsBusy = true;

                        EnvoyImporterServiceClient envoyService = new EnvoyImporterServiceClient();

                        try
                        {
                            envoyService.ImportArticleMasterStep1Completed += new EventHandler<EnvoyImporterService.ImportArticleMasterStep1CompletedEventArgs>(envoyService_ImportArticleMasterStep1Completed);
                            envoyService.ImportArticleMasterStep1Async(WorkspaceData.Instance.RangeReview);
                        }
                        catch (Exception ex)
                        {
                            envoyService.Abort();
                            IsBusy = false;
                            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);
                            throw ex;
                        }

                        break;
                    }
            }

            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);

        }

        private void RunStep2()
        {
            switch (WorkspaceData.Instance.Country.ArticlesImporter)
            {
                case Constants.ImportSettings.StandardExcelImporter:
                    {
                        IsBusy = true;

                        ExcelImporterServiceClient excelService = new ExcelImporterServiceClient();

                        try
                        {
                            excelService.ImportArticleMasterStep2Completed += new EventHandler<ExcelImporterService.ImportArticleMasterStep2CompletedEventArgs>(excelService_ImportArticleMasterStep2Completed);
                            excelService.ImportArticleMasterStep2Async(WorkspaceData.Instance.RangeReview);
                        }
                        catch (Exception ex)
                        {
                            excelService.Abort();
                            throw ex;
                        }

                        break;
                    }
                case Constants.ImportSettings.EnvoyImporter:
                    {
                        IsBusy = true;

                        EnvoyImporterServiceClient envoyService = new EnvoyImporterServiceClient();

                        try
                        {
                            envoyService.ImportArticleMasterStep2Completed += new EventHandler<EnvoyImporterService.ImportArticleMasterStep2CompletedEventArgs>(envoyService_ImportArticleMasterStep2Completed);
                            envoyService.ImportArticleMasterStep2Async(WorkspaceData.Instance.RangeReview);
                        }
                        catch (Exception ex)
                        {
                            envoyService.Abort();
                            throw ex;
                        }

                        break;
                    }
            }

            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);
        }

        private void RunStep3()
        {
            EnvoyImporterServiceClient envoyService = new EnvoyImporterServiceClient();
            try
            {
                envoyService.ImportArticleMasterStep3Completed += new EventHandler<ImportArticleMasterStep3CompletedEventArgs>(envoyService_ImportArticleMasterStep3Completed);
                envoyService.ImportArticleMasterStep3Async(WorkspaceData.Instance.RangeReview);
            }
            catch
            {
                envoyService.Abort();
                throw;
            }

            IsBusy = true;
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);
        }

        private void RunStep4()
        {
            EnvoyImporterServiceClient envoyService = new EnvoyImporterServiceClient();

            try
            {
                envoyService.ImportArticleMasterStep4Completed += new EventHandler<ImportArticleMasterStep4CompletedEventArgs>(envoyService_ImportArticleMasterStep4Completed);
                envoyService.ImportArticleMasterStep4Async(WorkspaceData.Instance.RangeReview);
            }
            catch
            {
                envoyService.Abort();
                throw;
            }

            IsBusy = true;
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);
        }


        void excelService_ImportArticleMasterStep1Completed(object sender, ExcelImporterService.ImportArticleMasterStep1CompletedEventArgs e)
        {
            if(e.Error == null)
            {
                (sender as ICommunicationObject).Close();
                RunStep1Callback(e.Result);
            }
            else
            {
                (sender as ICommunicationObject).Abort();
                IsBusy = false;
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);

                throw e.Error;
            }
        }

        void excelService_ImportArticleMasterStep2Completed(object sender, ExcelImporterService.ImportArticleMasterStep2CompletedEventArgs e)
        {
            if (e.Error == null)
            {
                (sender as ICommunicationObject).Close();
                RunStep2Callback(e.Result);
            }
            else
            {
                (sender as ICommunicationObject).Abort();
                IsBusy = false;
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);

                throw e.Error;
            }
        }


        void envoyService_ImportArticleMasterStep1Completed(object sender, EnvoyImporterService.ImportArticleMasterStep1CompletedEventArgs e)
        {
            if (e.Error == null)
            {
                (sender as ICommunicationObject).Close();
                RunStep1Callback(e.Result);
            }
            else
            {
                (sender as ICommunicationObject).Abort();
                IsBusy = false;
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);

                throw e.Error;
            }
        }

        void envoyService_ImportArticleMasterStep2Completed(object sender, EnvoyImporterService.ImportArticleMasterStep2CompletedEventArgs e)
        {
            if (e.Error == null)
            {
                (sender as ICommunicationObject).Close();
                RunStep2Callback(e.Result);
            }
            else
            {
                (sender as ICommunicationObject).Abort();
                IsBusy = false;
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);

                throw e.Error;
            }
        }

        void envoyService_ImportArticleMasterStep3Completed(object sender, ImportArticleMasterStep3CompletedEventArgs e)
        {

            IsBusy = false;
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);

            if (e.Error == null)
            {
                (sender as ICommunicationObject).Close();
                model.Results = e.Result;

                Step3ImagePath = "/Images/Pass-16.png";
                HasPassedCurrentStep = true;

                if (model.Results.Any())
                {
                    if (model.Results.Any(p => p.Workaround == Workaround.UnifyRepeatedNames))
                    {
                        IsUnifyEnabled = true;
                    }
                    else
                    {
                        IsUnifyEnabled = false;
                    }

                    if (model.Results.Any(p => p.ErrorType == ErrorType.Error))
                    {
                        Step3ImagePath = "/Images/NotPass-16.png";
                        HasPassedCurrentStep = false;
                    }

                    if (model.Results.Any(r => r.ItemId != 0))
                    {
                        ArticlesServiceClient service = new ArticlesServiceClient();
                        try
                        {
                            var ids = model.Results.Select(r => r.ItemId).Where(r => r != 0).ToList();
                            model.TempArticlesCache = new ObservableCollection<TempArticle>(service.GetTempArticlesByIds(ids));
                            model.TempArticles = model.TempArticlesCache;

                            service.Close();
                        }
                        catch
                        {
                            service.Abort();
                            throw;
                        }
                    }
                }
                else
                {
                    model.TempArticles.Clear();
                }

                IsBusy = false;
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.HasPassedCurrentStep);
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.Step3ImagePath);
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.TempArticles);
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.Results);
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsVisibleArticlesGV);
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsVisibleResultsGV);
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsUnifyEnabled);
            }
            else
            {
                (sender as ICommunicationObject).Abort();

                throw e.Error;
            }

            
        }

        void envoyService_ImportArticleMasterStep4Completed(object sender, ImportArticleMasterStep4CompletedEventArgs e)
        {
            IsBusy = false;
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);

            if (e.Error == null)
            {
                (sender as ICommunicationObject).Close();
                
                model.Results = e.Result;

                Step4ImagePath = "/Images/Pass-16.png";
                HasPassedCurrentStep = true;

                if (model.Results.Any())
                {
                    if (model.Results.Any(p => p.ErrorType == ErrorType.Error))
                    {
                        Step4ImagePath = "/Images/NotPass-16.png";
                        HasPassedCurrentStep = false;
                    }
                }

                IsBusy = false;
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.HasPassedCurrentStep);
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.Step4ImagePath);
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.Results);
                OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsVisibleResultsGV);
            }
            else
            {
                (sender as ICommunicationObject).Abort();

                throw e.Error;
            }
            
        }


        private void RunStep1Callback(List<ImporterResult> results)
        {
            model.Results = results;

            Step1ImagePath = "/Images/Pass-16.png";
            HasPassedCurrentStep = true;

            if (model.Results.Any())
            {
                if (model.Results.Any(p => p.ErrorType == ErrorType.Error))
                {
                    Step1ImagePath = "/Images/NotPass-16.png";
                    HasPassedCurrentStep = false;
                }
            }

            IsBusy = false;
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.HasPassedCurrentStep);
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.Step1ImagePath);
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.Results);
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsVisibleResultsGV);
        }

        private void RunStep2Callback(List<ImporterResult> results)
        {
            model.Results = results;

            Step2ImagePath = "/Images/Pass-16.png";
            HasPassedCurrentStep = true;

            if (model.Results.Any())
            {
                if (model.Results.Any(p => p.ErrorType == ErrorType.Error))
                {
                    Step2ImagePath = "/Images/NotPass-16.png";
                    HasPassedCurrentStep = false;
                }
            }

            IsBusy = false;
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsBusy);
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.HasPassedCurrentStep);
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.Step2ImagePath);
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.Results);
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.IsVisibleResultsGV);
        }



        private void SaveTempArticles()
        {
            model.SaveTempArticles();
            OnPropertyChanged<ArticlesImporterViewModel>(p => p.TempArticles);
        }

        private void UnifyRepeatedArticles()
        {
            RangeReviewStore sameStore = null;

            RangeReviewsServiceClient service = new RangeReviewsServiceClient();
            try
            {
                sameStore = service.GetRangeReviewSameStore(WorkspaceData.Instance.RangeReview.Id);
                service.Close();
            }
            catch
            {
                service.Abort();
                throw;
            }

            if (sameStore != null)
            {
                var repeatedNames = from art in model.TempArticlesCache
                                    group art by art.Name into g
                                    let count = g.Count()
                                    where count > 1
                                    select g.Key;

                var articlesWithSameName = model.TempArticlesCache.Where(art => repeatedNames.Contains(art.Name)).ToList();

                var names = model.TempArticlesCache.Select(a => a.Name).Distinct();

                List<TempArticle> sameStoreArticles = model.GetSameStoreArticles(sameStore.Id);

                foreach (var name in names)
                {
                    //Tomo el de la tienda modelo. 
                    TempArticle targetArticle = sameStoreArticles.FirstOrDefault(x => x.Name == name);

                    //Si no existe en la modelo tomo el first.
                    if (targetArticle == null)
                    {
                        targetArticle = articlesWithSameName.First(x => x.Name == name);
                    }

                    articlesWithSameName.Remove(targetArticle);

                    articlesWithSameName.Where(a => a.Name == name)
                                        .ToList()
                                        .ForEach(art =>
                                        {
                                            art.NewCode = targetArticle.Code;
                                        });

                }


                if (articlesWithSameName.Any())
                {
                    //Si es un importador unificado actualizo también los codigos de la tabla TempArticleSales
                    if (!WorkspaceData.Instance.Country.IsArticleMasterSeparateFile)
                    {
                        model.UpdateSales(articlesWithSameName);
                    }
                    else
                    {
                        //TODO: Implementar combinación de duplicados para ArticleMasters que vienen por separado.
                    }
                }

                RetryCurrentStep();
            }
            else
            {
                throw new ARRException(Errors.SameStoreIsRequired, ExceptionSeverity.Validation);
            }
        }
    }
}
